import wx
from zope import interface
import os, sys
import cPickle as pickle
from amara import binderytools

APPLICATION_INSTALL_DIR = os.environ.get('SIMPLEWATCHER_INSTALL')
if not APPLICATION_INSTALL_DIR:
    raise EnvironmentError("must set environment variable SIMPLEWATCHER_INSTALL")
sys.path.append('%s/lib' % APPLICATION_INSTALL_DIR)

from watch_builder.builder.schema import SchemaConstraint
from watch_builder.gui.watchobjects import interfaces as wb_ints
from watch_builder.gui import utils



class SimpleWatcherDataObject(wx.CustomDataObject):
    """base class for watch data objects"""
    interface.implements(wb_ints.ISimpleWatcherDataObject)

    _default_image = "blank.gif"
    _xml_build_attrs = []
    _valid_children = []
    _embedded_resources = []
    _only_child = []
    _parent = None
    def __init__(self, *args, **kwargs):
        wx.CustomDataObject.__init__(self, wx.CustomDataFormat("WatcherObjectDataFormat"))
        # build our image, if we were given an new file name
        self.setImage(kwargs.get('image', self._default_image))
        # set all kwarg attrs relevant to building the object's xml
        for (attr, xattr) in self._xml_build_attrs:
            setattr(self, attr, kwargs.get(attr, ''))
        self._children = []
        self.build_schema()
        

    def setObject(self, obj):
        self.SetData(pickle.dumps(obj))
    
    def getObject(self):
        return pickle.loads(self.GetData())
    

    def watchBuilderXml(self):
        raise NotImplementedError("Must define in subclass!")
    
    
    def setImage(self, filename):
        self.image = utils.wxImageBuilder(filename)
    
    def build_schema(self):
        self.schema = SchemaConstraint(self)

    def fromXml(self, xml):
        """reset attributes on the object from the xml"""
        doc = binderytools.bind_string(xml)
        for attr, xattr in self._xml_build_attrs:
            try:
                # this will throw an index error if there is no matching value, which is fine
                value = doc.xml_xpath(xattr)[0]
                if hasattr(value, "nodeValue"):
                    value = getattr(value, "nodeValue")
                else:
                    value = str(value)
            except IndexError:
                value = ""
            setattr(self, attr, value)


class RootDataObject(SimpleWatcherDataObject):
    """root object for watch construction"""
    interface.implements(wb_ints.IRootDataObject)
    def __init__(self, *args, **kwargs):
        super(RootDataObject, self).__init__(*args, **kwargs)
        self.buildDefaults()
        # build our image, if we were given an new file name
        self.setImage(kwargs.get('image', self._default_image))
        # set all kwarg attrs relevant to building the object's xml
        for (attr, xattr) in self._xml_build_attrs:
            setattr(self, attr, kwargs.get(attr, ''))
        self._children = []
        self.build_schema()
    
    def buildDefaults(self):
        self._default_image = "root.gif"
        self._valid_children = [wb_ints.IWatchDataObject, wb_ints.ICommentDataObject]
        self._xml_build_attrs = []
        self._embedded_resources = [wb_ints.ICommentDataObject]
        self._only_child = [wb_ints.IWatchDataObject]


class CommentDataObject(SimpleWatcherDataObject):
    """comment data object"""
    interface.implements(wb_ints.ICommentDataObject)

    def __init__(self, *args, **kwargs):
        super(CommentDataObject, self).__init__(*args, **kwargs)
        self.buildDefaults()
        # build our image, if we were given an new file name
        self.setImage(kwargs.get('image', self._default_image))
        # set all kwarg attrs relevant to building the object's xml
        for (attr, xattr) in self._xml_build_attrs:
            setattr(self, attr, kwargs.get(attr, ''))
        self._children = []
        self.build_schema()
    
    def buildDefaults(self):
        self._default_image = "comment.gif"
        self._valid_children = []
        self._embedded_resources = []
        self._xml_build_attrs = []
        self._only_child = []